package net.easyjava.base.aspect.log;

import com.alibaba.fastjson.JSONObject;
import net.easyjava.base.bean.mongodb.RequestLogBean;
import net.easyjava.base.service.mongodb.RequestLogService;
import net.easyjava.base.utils.baidu.BaiduMapUtils;
import net.easyjava.base.utils.baidu.bean.LocationBean;
import net.easyjava.tools.http.request.RequestTools;
import net.easyjava.tools.log.annotation.Log;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

/**
 * Created by wenxiaoning on 15/12/19.
 */
@Aspect
@Component
public class ControllerLogAspect {
    private Logger logger = LoggerFactory.getLogger(this.getClass().getName());
    @Resource
    private RequestLogService requestLogService;
    private Long consTime;
    private RequestLogBean requestLogBean;

    /**
     * 记录api项目中controller的操作日志
     * @throws Exception
     */
    @Before("execution(* net.easyjava.*.controller.*Controller.*(..))")
    public void beforeApiController() throws Exception{
        consTime = System.currentTimeMillis();
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest();
        request.setAttribute("consTime",consTime);
        //准备工作
        initBefore(request);

        Executor executor = Executors.newSingleThreadExecutor();
        executor.execute(new Runnable() {
            @Override
            public void run() {
                saveRequestLogBean();
            }
        });

        logger.info("开始工作...");
    }

    /**
     * 保存 requestLogBean
     */
    public void saveRequestLogBean(){
        synchronized (requestLogBean){
            requestLogService.save(requestLogBean);
            logger.info("接口访问日志保存完毕 id:{}",requestLogBean.getId());

        }
    }

    /**
     * 初始化 requestLogBean
     * @param request
     */
    public void initBefore(HttpServletRequest request){


        String ip= RequestTools.getIP(request);
        String referer = RequestTools.getHeadReferer(request);
        String realUrl = RequestTools.getRealUrl(request);
        String method = request.getMethod();
        Map<String,String> params = RequestTools.getParams(request);
        Map<String,String> heads = RequestTools.getHeads(request);
        //获取地理位置信息
        LocationBean locationBean = BaiduMapUtils.getLocation();

        requestLogBean = new RequestLogBean();
        requestLogBean.setFromIP(ip);
        requestLogBean.setFromUrl(referer);
        requestLogBean.setTargetUrl(realUrl);
        requestLogBean.setMethod(method);
        requestLogBean.setParams(params);
        requestLogBean.setHeads(heads);
        requestLogBean.setDescription("");
        requestLogBean.setLocation(JSONObject.parseObject(JSONObject.toJSON(locationBean).toString(), Map.class));


        logger.info("接口:{}开始执行 准备工作...",new Object[]{requestLogBean.getId()});
        logger.info("fromIP:{}",ip);
        logger.info("method:{}",method);
        logger.info("url:{}",realUrl);
        logger.info("params:{}",params.toString());
        logger.info("user-agent:{}",RequestTools.getHeadUserAgent(request));
        logger.info("fromUrl:{}",referer);


    }

    /**
     * 拦截controller层所有带有注解的方法
     * @throws Exception
     */
    @AfterReturning(value = "execution(* net.easyjava.*.controller.*Controller.*(..))")
    public void AfterReturning() throws Exception {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest();



//        synchronized (consTime){
//            long totalTime = System.currentTimeMillis() - consTime;//Long.valueOf(request.getParameter("consTime"));
//            requestLogBean.setTotalTime((int)totalTime);
//            logger.info("接口:{} 结束，耗时:{}ms", new Object[]{requestLogBean.getId(), totalTime});
//        }

//        Executor executor = Executors.newSingleThreadExecutor();
//        executor.execute(new Runnable() {
//            @Override
//            public void run() {
//                updateRequestLogBean();
//            }
//        });

        logger.info("----------------------------------------------------------------");

//        consTime = 0L;
    }

    private void updateRequestLogBean(){
        synchronized (this.requestLogBean){
            requestLogService.update(this.requestLogBean);
        }
        requestLogBean = null;
    }
}
